Mythril and Slither: Overview, Detection Capabilities, and Use Cases

Mythril and Slither are two widely-used tools in the Ethereum security ecosystem, designed to identify vulnerabilities and risks in smart contracts. They provide different approaches to static and dynamic analysis, each having strengths in particular areas of contract auditing.


Mythril Overview

Mythril is a security analysis tool specifically built for detecting vulnerabilities in Ethereum smart contracts. It operates by executing symbolic execution, SMT (Satisfiability Modulo Theories) solving, and taint analysis. Mythril can identify a wide variety of common Solidity vulnerabilities, with customizable modules allowing for detailed and flexible analysis.

Types of Issues Mythril Detects:

Each module specializes in identifying specific vulnerabilities in smart contracts:

  1. Delegate Call To Untrusted Contract: Detects cases where contracts use delegate calls to untrusted contracts, which can result in loss of control.

  2. Dependence on Predictable Variables: Identifies reliance on easily predictable variables (e.g., block.timestamp or blockhash).

  3. Ether Thief: Detects situations where the contract can send Ether to arbitrary accounts.

  4. Exceptions: Identifies incorrect handling of exceptions, which can break contract logic.

  5. External Calls: Detects unsafe external contract calls, which could lead to reentrancy or other attacks.

  6. Integer: Finds integer overflow and underflow issues, potentially leading to erroneous calculations or contract behavior.

  7. Multiple Sends: Detects contracts that send Ether to multiple accounts, potentially exposing them to denial of service (DoS) risks.

  8. Suicide: Finds vulnerabilities where unauthorized users can trigger the self-destruct function.

  9. State Change External Calls: Detects situations where external calls are made after state changes, leading to reentrancy vulnerabilities.

  10. Unchecked Retval: Identifies cases where return values of critical functions are not checked, leading to logic errors.

  11. User-Supplied Assertion: Detects contracts using user-supplied data in assertions, which can be manipulated to crash the contract.

  12. Arbitrary Storage Write: Finds vulnerabilities where unauthorized users can write to arbitrary storage locations.

  13. Arbitrary Jump: Detects when arbitrary jumps are possible, leading to unpredictable behavior.

Example Situation for Mythril:

A developer wants to check for integer overflow vulnerabilities in their smart contract that deals with token transfers. Mythril’s Integer module can detect this issue through symbolic execution and ensure that safe math is implemented properly.


Slither Overview

Slither is a static analysis tool for Solidity that provides a faster, more lightweight alternative to symbolic execution tools. It offers high confidence results on various Solidity patterns, identifying vulnerabilities that can affect the contract’s functionality, security, and efficiency.

Types of Issues Slither Detects:

Slither has a broader range of detectors organized into categories by impact and confidence. Below are some detectors and what they reveal:

Num Detector What It Detects Impact Confidence
1 abiencoderv2-array Storage ABIEncoderV2 array High High
2 arbitrary-send-erc20 Detects arbitrary transferFrom ERC20 calls High High
12 suicidal Functions that allow anyone to self-destruct the contract High High
13 uninitialized-state Uninitialized state variables, which can lead to undefined behavior High High
25 reentrancy-eth Reentrancy vulnerabilities that lead to Ether theft High Medium
29 weak-prng Weak pseudorandom number generation, which can be exploited High Medium
48 tx-origin Dangerous usage of tx.origin, making contracts vulnerable to phishing attacks Medium Medium
51 uninitialized-local Uninitialized local variables that may lead to unexpected behavior Medium Medium
89 cache-array-length Detects inefficient loops that use array.length repeatedly in loop conditions Optimization High
92 immutable-states Identifies state variables that could be declared immutable to save gas Optimization High

Example Situation for Slither:

A developer is concerned about reentrancy vulnerabilities in their Ethereum contract, particularly in functions that handle Ether transfers. Using Slither’s reentrancy-eth detector, they can efficiently identify unsafe patterns such as external calls made before internal state changes, which are prime targets for reentrancy attacks.


Comparison: When to Use Mythril vs. Slither

Tool Best for Strengths Weaknesses
Mythril - Complex analysis where symbolic execution is needed
- Verifying contract behavior under specific conditions
- Symbolic execution allows for detailed coverage of potential contract states
- Can detect deep vulnerabilities like integer overflow, unchecked retval, etc.
- Slower due to the depth of analysis
- May generate false positives due to over-analysis
Slither - Quick detection of common Solidity anti-patterns
- Optimizing contract for gas efficiency
- Very fast, works on static code
- Focused on Solidity-specific issues
- High accuracy with confidence indicators
- Lacks deep symbolic analysis
- Doesn’t explore possible execution states

Example of a Custom Slither Module

Creating a custom Slither module (also called a detector) allows you to extend Slither’s analysis capabilities and identify specific patterns or vulnerabilities in your smart contracts. In this example, we will create a custom Slither detector that identifies contracts using low-level call() without checking the return value—a common mistake that could lead to security vulnerabilities, as the failure of the call might go unnoticed.

Here is a step-by-step guide to creating a custom Slither module.


Step 1: Set Up the Environment

First, make sure you have Slither installed. You can install it using pip:

pip install slither-analyzer

Next, create a directory structure for your custom module. For this example, let’s call the file custom_call_check.py.

Step 2: Write the Custom Detector

In the file custom_call_check.py, define a new class that extends Slither’s Detector class. Slither provides various hooks and helpers to interact with Solidity contracts and functions.

from slither.core.detectors.abstract_detector import AbstractDetector, DetectorClassification
from slither.slithir.operations import LowLevelCall

class CustomCallCheck(AbstractDetector):
    """
    This detector identifies the use of low-level `call()` without checking the return value.
    """

    ARGUMENT = 'call-without-check'
    HELP = 'Detect low-level call without checking the return value'
    IMPACT = DetectorClassification.HIGH
    CONFIDENCE = DetectorClassification.HIGH

    def _detect(self):
        issues = []

        # Iterate through each contract
        for contract in self.compilation_unit.contracts:
            # Iterate through each function in the contract
            for function in contract.functions_and_modifiers:
                # Iterate through the intermediate representation (IR) instructions of the function
                for ir in function.slithir_operations:
                    # We are interested in low-level calls
                    if isinstance(ir, LowLevelCall):
                        # Check if the return value of the call is ignored (i.e., unused)
                        if not ir.result:
                            # Create a unique issue for each detected instance
                            issue_info = [
                                f"Function {function.name} in contract {contract.name} "
                                f"uses low-level call() without checking the return value."
                            ]
                            issues.append(self.generate_result(issue_info))

        return issues

Explanation:

Step 3: Running the Custom Module

To run this custom detector, you would first save the custom_call_check.py file in the proper directory under Slither’s detectors/ directory or provide it as a custom argument in your setup.

You can now invoke the custom detector like this:

slither . --detect call-without-check

This will run the Slither analysis and include your custom detector, scanning all contracts in the current directory (.) for low-level calls that do not check the return value.

Example Solidity Contract (for testing)

Let’s test this detector with a simple vulnerable Solidity contract:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Vulnerable {
    function sendEther(address payable recipient) public {
        // Low-level call without checking the return value
        recipient.call{value: 1 ether}("");
    }
}

In this contract, the call() function is used to transfer Ether, but the return value is not checked. This can lead to unhandled failures, and the custom detector should flag it as a potential issue.

Step 4: Output

After running the custom detector, you should see output similar to the following:

INFO:Slither:Vulnerable uses low-level call() without checking the return value
  Function sendEther in contract Vulnerable uses low-level call() without checking the return value.

This confirms that the custom detector works as expected, identifying contracts that fail to check return values from low-level calls.


Conclusion

Both Mythril and Slither serve as crucial tools in Ethereum smart contract development, helping developers identify and mitigate security vulnerabilities. Depending on the need—deep symbolic execution or fast, static code analysis—one tool may be more appropriate than the other.

By combining the strengths of both tools, developers can create more secure and efficient smart contracts on Ethereum.